// 《围棋》作者版权所有。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package runtime

import (
	"internal/abi"
	"internal/goarch"
	"internal/goexperiment"
	"runtime/internal/math"
	"unsafe"
)

// 应该是不安全的内置设备。指针？
// go:nosplit 
func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
	return unsafe.Pointer(uintptr(p) + x)
}

// getg返回指向当前g的指针。
// 编译器将对该函数的调用重写为指令
// 直接（从TLS或专用寄存器）获取g。
func getg() *g

// mcall从g切换到g0堆栈并调用fn（g），
// 其中g是发出调用的goroutine。
// mcall将g当前的PC/SP保存在g->sched中，以便以后恢复。
// fn负责安排稍后的执行，通常是通过在数据结构中记录
// g，使某些内容稍后调用ready（g）。
// 稍后，当g被重新安排时，McCall将返回到原来的goroutine g。
// fn不得返回；通常，它以调用schedule结束，让m 
// 运行其他goroutine。
// 
// 只能从g堆栈（非g0，非gsignal）调用mcall。
// 
// 这不能是go:noescape:如果fn是堆栈分配的闭包，
// fn将g放在运行队列中，并且g在fn返回之前执行，
// 闭包将在仍在执行时失效。
func mcall(fn func(*g))

// systemstack在系统堆栈上运行fn。
// 如果从每个OS线程（g0）堆栈调用systemstack，或者
// 如果从信号处理（gsignal）堆栈调用systemstack，
// systemstack直接调用fn并返回。否则，systemstack将从普通goroutine的有限堆栈调用。在这种情况下，systemstack将
// 切换到每个OS线程堆栈，调用fn，然后切换回。
// 通常使用func-literal作为参数，以便
// 与调用
// 到系统堆栈的代码共享输入和输出：
// 
// 。。。设置y。。。
// systemstack（func（）{
// x=bigcall（y）
// }）
// 。。。使用x。。。
// 
// go:noescape 
func systemstack(fn func())

var badsystemstackMsg = "fatal: systemstack called from unexpected goroutine"

// go:nosplit 
// go:NOWRITEBRIERREC 
func badsystemstack() {
	sp := stringStructOf(&badsystemstackMsg)
	write(2, sp.str, int32(sp.len))
}

// memclrNoHeapPointers清除从ptr开始的n字节。
// 
// 通常应该使用typedmemclr。memclrNoHeapPointers应该是
// 仅当调用者知道*ptr不包含堆指针
// 时使用，因为：
// 
// /*ptr是初始化内存，其类型是无指针的，或者
// 
// ptr是未初始化的内存（例如，正在被重新使用的内存
// ），因此只包含“垃圾”。
// 
// memclrNoHeapPointers确保如果ptr是指针对齐的，且n 
// 是指针大小的倍数，则任何指针对齐的、
// 指针大小的部分都会被原子清除。尽管函数
// name，但这是必需的，因为该函数是typedmclr和memclrHasPointers的底层
// 实现。详见
// memmove文件。
// 
// 此函数的（特定于CPU的）实现在memclr_*中。s、 
// 
// go:noescape 
func memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr)

// go:linkname reflect_memclrNoHeapPointers reflect。memclrNoHeapPointers 
func reflect_memclrNoHeapPointers(ptr unsafe.Pointer, n uintptr) {
	memclrNoHeapPointers(ptr, n)
}

// memmove将n个字节从“from”复制到“to”。
// 
// memmove确保“from”中的任何指针都是用
// 不可分割的写操作写入“to”，这样racy reads就无法观察到
// 半写指针。这是防止垃圾
// 收集器观察无效指针所必需的，与非托管语言中的memmove 
// 不同。但是，memmove只需要执行
// 如果“from”和“to”可能包含指针，那么它只能是
// 如果“from”、“to”和“n”都是单词对齐的，那么它的大小写就可以了。
// 
// 实现在memmove_*中。s、 
// 
// go:noescape 
func memmove(to, from unsafe.Pointer, n uintptr)

// 外部程序集调用memmove。确保它有ABI包装。
// go:linkname memmove 

// go:linkname reflect_memmove reflect。memmove-
func reflect_memmove(to, from unsafe.Pointer, n uintptr) {
	memmove(to, from, n)
}

// 导出测试值
const hashLoad = float32(loadFactorNum) / float32(loadFactorDen)

// go:nosplit-
func fastrand() uint32 {
	mp := getg().m
	// 实现wyrand:https:
	// 仅支持数学运算的平台。Mul64可以降低
	// 由编译器编写的文件应在此列表中。
	if goarch.IsAmd64|goarch.IsArm64|goarch.IsPpc64|
		goarch.IsPpc64le|goarch.IsMips64|goarch.IsMips64le|
		goarch.IsS390x|goarch.IsRiscv64 == 1 {
		mp.fastrand += 0xa0761d6478bd642f
		hi, lo := math.Mul64(mp.fastrand, mp.fastrand^0xe7037ed1a0b428db)
		return uint32(hi ^ lo)
	}

	// 实现xorshift64+：两个32位xorshift序列相加。
	// Shift三元组[17,7,16]的计算方法如Marsaglia的
	// Xorshift论文所示：https:
	// 此生成器通过SmallCrush套件，TestU01框架的一部分：
	// http:
	t := (*[2]uint32)(unsafe.Pointer(&mp.fastrand))
	s1, s0 := t[0], t[1]
	s1 ^= s1 << 17
	s1 = s1 ^ s0 ^ s1>>7 ^ s0>>16
	t[0], t[1] = s0, s1
	return s0 + s1
}

// go:nosplit 
func fastrandn(n uint32) uint32 {
	// 这与fastrand（）类似，但速度更快。
	// 参见https:
	return uint32(uint64(fastrand()) * uint64(n) >> 32)
}

// go:linkname sync_fastrandn sync。fastrandn 
func sync_fastrandn(n uint32) uint32 { return fastrandn(n) }

// go:linkname net_fastrand net。fastrand 
func net_fastrand() uint32 { return fastrand() }

// go:linkname os_fastrand os。fastrand 
func os_fastrand() uint32 { return fastrand() }

// in internal/bytealg/equal_*。s 
// go:noescape 
func memequal(a, b unsafe.Pointer, size uintptr) bool

// noescape在转义分析中隐藏指针。noescape是
// 标识函数，但escape分析认为
// 输出不取决于输入。noescape是内联的，目前
// 编译到零指令。
// 小心使用！
// go:nosplit 
func noescape(p unsafe.Pointer) unsafe.Pointer {
	x := uintptr(p)
	return unsafe.Pointer(x ^ 0)
}

// 并非所有的cgocallback帧实际上都是cgocallback，
// 因此并非所有的cgocallback帧都有这些参数。将它们标记为uintpttr，这样当参数不存在时，GC 
// 不会误解内存。
// cgocallback不是从Go调用的，而是从crosscall2调用的。
// 这又调用了cgocallbackg，在这里我们可以找到
// 指针声明的参数。
func cgocallback(fn, frame, ctxt uintptr)

func gogo(buf *gobuf)

func asminit()
func setg(gg *g)
func breakpoint()

// reflectcall使用stackArgs、StackArgsize、
// frameSize和regArgs描述的参数调用fn。
// 
// 堆栈上传递的参数和堆栈上传递的返回值的空间
// 必须根据ABI设置在stackArgs（总长度为
// StackArgsize）指向的空间。
// 
// stackRetOffset必须是某个值<=StackArgsize，指示返回值空间开始的stackArgs内的
// 偏移量。
// 
// frameSize是stackArgs处参数帧的总大小，因此必须是>=StackArgsize。它必须包含用于溢出
// 堆栈增长和抢占的寄存器参数的额外空间。
// 
// TODO（mknyszek）：一旦我们不需要额外的溢出空间，请删除frameSize，
// 因为frameSize将与StackArgsize冗余。
// 
// 寄存器中传递的参数必须根据ABI以Regarg格式排列。
// regArgs将保存调用后传入寄存器的所有返回值。
// 
// reflectcall将堆栈参数从stackArgs复制到goroutine堆栈，一旦fn完成，
// 然后将StackArgsize stackRetOffset字节复制回stackArgs中的返回空间
// 。它还可以在调用fn之前从
// regArgs中“unspill”参数寄存器，并在调用fn之后立即将它们返回到regArgs中。如果堆栈上返回了结果，则调用方应将参数帧类型作为stackArgsType传递，以便在复制过程中，反射调用可以执行适当的写屏障。
// 
// reflectcall需要Regarg。要填充的ReturnIsPtr指示返回路径上的哪个
// 寄存器将包含Go指针。然后，它将
// 这些指针存储在regArgs中。PTR，使其对GC可见。
// 
// 包反射传递帧类型。在包运行时中，只有
// 一个调用将结果复制回syscall_窗口中的callbackWrap。go，它
// 不传递帧类型，这意味着没有调用写入障碍。查看
// 呼叫站点以获取正当性。
// 
// Package reflect通过链接名访问此符号。
// 
// 传递给reflectcall的参数不会转义。该类型仅在reflectcall的非常有限的被调用方中使用，stackArgs被复制，而
// regArgs仅在reflectcall帧中使用。goexit是每个goroutine调用堆栈顶部的返回存根。
func reflectcall(stackArgsType *_type, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)

func procyield(cycles uint32)

type neverCallThisFunction struct{}

// 每个goroutine堆栈的构造方式就像goexit调用了
// goroutine的入口点函数一样，因此当入口点
// 函数返回时，它将返回到goexit，goexit将调用goexit 1 
// 来执行实际的退出。
// 
// 此函数不能直接调用。打电话给goexit1。
// gentraceback假设goexit终止堆栈。堆栈上的直接
// 调用将导致gentraceback过早停止遍历堆栈
// 如果存在剩余状态，它可能会恐慌。
func goexit(neverCallThisFunction)

// publicationBarrier执行存储/存储屏障（“发布”
// 或“导出”屏障）。初始化一个对象和使另一个处理器可以访问该对象之间需要某种形式的同步。如果没有同步，初始化
// 写入和“发布”写入可能会被重新排序，从而允许
// 其他处理器跟随指针并观察未初始化的
// 对象。一般来说，应该使用更高级别的同步，例如锁定或原子指针写入。publicationBarrier是
// 当这些都不是选项时，例如在内存管理器的实现中。
// 
// 读取端没有相应的障碍，因为读取
// 端自然具有数据依赖顺序。
// Go支持或可能支持的所有架构都会自动执行
// 数据依赖顺序。
func publicationBarrier()

// getcallerpc返回调用者的调用者的程序计数器（PC）。
// getcallersp返回其调用者的调用者的堆栈指针（SP）。
// 实现可能是一个编译器固有的；
// 没有必要在每个平台上实现这一点的代码。
// 
// 例如：
// 
// func f（arg1，arg2，arg3 int）{
// pc:=getcallerpc（）
// sp:=getcallersp（）
// }
// 
// 对GetCallerRPC和getcallersp的调用必须在被询问的
// 框架中完成。
// 
// getcallersp的结果在返回时是正确的，
// 但它可能会因对函数
// 的任何后续调用而无效，该函数可能会重新定位堆栈以增加或缩小堆栈。
// 一般的规则是，getcallersp的结果应该立即使用
// 并且只能传递给nosplit函数。

// go:noescape 
func getcallerpc() uintptr

// go:noescape 
func getcallersp() uintptr // 在所有平台上作为内部实现

// getclosureptr返回指向当前闭包的指针。
// getclosureptr只能在赋值语句
// 在函数项中使用。此外，必须在调用函数
// 以便函数prolog不会阻塞闭包寄存器。
// 的声明中指定go:nosplit指令
// 例如：
// 
// /go:nosplit 
// func f（arg1，arg2，arg3 int）{
// dx:=getclosureptr（）
// }
// 
// 编译器将对该函数的调用重写为指令，从已知寄存器获取
// （x86架构上的DX等）直接。
func getclosureptr() uintptr

// go:noescape 
func asmcgocall(fn, arg unsafe.Pointer) int32

func morestack()
func morestack_noctxt()
func rt0_go()

// return0是一个存根，用于从deferproc返回0。
// 在deferproc的最后调用它，以发出信号
// 调用Go函数，它不应跳转
// 以延迟返回。
// 在asm_*中。s 
func return0()

// 在asm_*中。s 
// 未直接调用；此处的定义提供了用于回溯的类型信息。
// 它们必须与reflectcall具有相同的签名（arg指针映射）。
func call16(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call32(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call64(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call128(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call256(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call512(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call1024(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call2048(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call4096(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call8192(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call16384(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call32768(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call65536(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call131072(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call262144(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call524288(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call1048576(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call2097152(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call4194304(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call8388608(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call16777216(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call33554432(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call67108864(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call134217728(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call268435456(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call536870912(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)
func call1073741824(typ, fn, stackArgs unsafe.Pointer, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs)

func systemstack_switch()

// 将n四舍五入为a的倍数。a必须是2的幂。
func alignUp(n, a uintptr) uintptr {
	return (n + a - 1) &^ (a - 1)
}

// 将n向下舍入为a的倍数。a必须是2的幂。
func alignDown(n, a uintptr) uintptr {
	return n &^ (a - 1)
}

// divRoundUp返回ceil（不适用）。
func divRoundUp(n, a uintptr) uintptr {
	// a通常是二的幂。这将被内联，
	// 编译器将优化除法。
	return (n + a - 1) / a
}

// checkASM报告程序集运行时检查是否已通过。
func checkASM() bool

func memequal_varlen(a, b unsafe.Pointer) bool

// 如果x为假，bool2int返回0，如果x为真，则返回1。
func bool2int(x bool) int {
	// 避免分支机构。在SSA编译器中，它会编译成
	// 这正是您想要的。
	return int(uint8(*(*uint8)(unsafe.Pointer(&x))))
}

// 在连throw都可能无法工作的情况下，abort会使运行时崩溃。一般来说，它应该做一些调试器可以识别
// （例如x86上的INT3）。
// 信号处理程序会识别abort中的崩溃，该处理程序将尝试立即中断运行时
// 。
func abort()

// 从编译代码中调用；申报兽医；不要在路上打电话。
func gcWriteBarrier()
func duffzero()
func duffcopy()

// 从生成的链接器调用。初始化数组；宣布接受兽医检查；不要在路上打电话。
func addmoduledata()

// 由信号处理器注入，用于发送紧急信号。
// 初始化任何在调用时具有固定含义的寄存器，但
// 在主体和调用中是划痕。
// 在许多平台上，它只是跳转到sigpanic。
func sigpanic0()

// intArgRegs用于运行时的各种寄存器分配
// 算法实现。其中包括：。
// -终结器（mfinal.go）
// -Windows回调（syscall_Windows.go）
// /
// 这两个都是算法的精简版本，因为它们只需处理一部分情况（仅限终结器
// 获取指针或接口参数，转到Windows回调
// 不支持浮点）。
// 
// 在测试此软件包时，应小心修改，通常仅对
// 进行修改。
// 
// 它的设置不应高于其内部/abi 
// 常量对应项，因为系统依赖于一个
// 结构，该结构至少足以容纳系统支持的
// 寄存器。
// 
// 受finlock保护。
var intArgRegs = abi.IntArgRegs * (goexperiment.RegabiArgsInt | goarch.IsAmd64)
